package com.example.securityproject.demos.handler;

import com.example.securityproject.demos.common.Business2Exception;
import com.example.securityproject.demos.common.BusinessException;
import com.example.securityproject.demos.common.CommonResult;
import com.example.securityproject.demos.common.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ValidationException;
import java.util.List;

/*
 * @description:全局异常（尽可能捕获所有异常，才会统一返回。可以自己给code和message。不然会出现不可控的返回）
 * @author: Jiangjb
 * @date: 2022/6/25 0:09
 **/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理@Validated参数校验失败异常
     *
     * @param exception 异常类
     * @return 响应
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<String> exceptionHandler(MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        StringBuilder stringBuilder = new StringBuilder();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            if (errors != null) {
                errors.forEach(p -> {
                    FieldError fieldError = (FieldError) p;
                    log.warn("Bad Request Parameters: dto entity [{}],field [{}],message [{}]", fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage());
                    stringBuilder.append(fieldError.getDefaultMessage());
                });
            }
        }
        return CommonResult.error(-1, stringBuilder.toString());
    }

    /**
     * 处理空指针的异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    public CommonResult exceptionHandler(HttpServletRequest req, NullPointerException e) {
        log.error("发生空指针异常！原因是:", e.getMessage());
        return CommonResult.error(ResultCode.EXCEPTION_NULLPOINTER);
    }

    /**
     * 处理自定义异常（code和message 直接从 throw new BusinessException(code, message) 中来）
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    public CommonResult exceptionHandler(HttpServletRequest req, BusinessException e) {
        log.error("发生自定义异常！原因是:", e.getDescription());
        return CommonResult.error(e.getCode(), e.getDescription());
    }

    @ExceptionHandler(value = Business2Exception.class)
    public CommonResult exception2Handler(HttpServletRequest req, BusinessException e) {
        log.error("发生自定义异常2！原因是:", e.getDescription());
        return CommonResult.error(e.getCode(), e.getDescription());
    }

    @ExceptionHandler(ValidationException.class)
    public CommonResult handleValidationException(HttpServletRequest request, ValidationException ex) {
        log.error("{} ValidationException：{} ", request.getRequestURI(), ex.getMessage());
        return CommonResult.error(ex.getMessage());
    }

    /**
     * 处理其他异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public CommonResult exceptionHandler(HttpServletRequest req, Exception e) {
        log.error("其它异常！原因是:", e.getMessage());
        return CommonResult.error(ResultCode.HTTP_FAIL.getCode(), e.getMessage());
    }
}

